#!/bin/bash
#
# rbdmap Ceph RBD Mapping
# This version supports the keyring file rather than just the ID.

# Based on work by Laurent Barbe
# http://cephnotes.ksperis.com/blog/2014/01/09/map-rbd-kernel-without-install-ceph-common
# http://cephnotes.ksperis.com/downloads/rbdmap

RBDMAPFILE="/etc/ceph/rbdmap"
CONF="/etc/ceph/ceph.conf"
DESC="RBD Mapping"

modprobe rbd || exit 1

do_map() {
  if [ ! -f "$RBDMAPFILE" ]; then
    echo "*** $DESC : No $RBDMAPFILE found."
    exit 0
  fi

  echo "Starting $DESC"
  # Read /etc/ceph/rbdmap to create non-existant mapping
  newrbd=
  RET=0
  while read -r DEV PARAMS; do
    case "$DEV" in
      ""|\#*)
        continue ;;
      */*) ;;
      *)
        DEV=rbd/$DEV ;;
    esac

  if [ ! -b /dev/rbd/$DEV ]; then
      echo "Map: $DEV"
      #mons=`egrep 'mon[ _]host' $CONF | cut -f2 -d'=' | sed 's/ //g'` # choose the right selector for the configuration
      mons=`egrep 'mon_addr' $CONF | cut -f2 -d'=' | sed 's/ //g' | tr '\n' ',' | sed 's/.$//'`
      rbddev=`echo $DEV | tr '/' ' '`

      IFS=, read -r -a params <<< "$PARAMS"
      for opt in "${params[@]}"; do
        IFS="=" read -r key val <<< "$opt"
        case $key in
              id) name=$val ;;
              secret) secret=$val ;;
              keyring) secret=`sed -rn 's/^[[:space:]]*key[[:space:]]=[[:space:]]*//p' $val` ;;
        esac
      done
      if [ -n "$secret" ] && [ -n "$name" ]; then
        echo "$mons name=$name,secret=$secret $rbddev" > /sys/bus/rbd/add
        [ $? -ne "0" ] && RET=1
        newrbd="yes"
        timeout=0
        while [[ ! -e /dev/rbd/$DEV  && timeout -lt 20 ]]; do
          sleep 0.5
          timeout=$((timeout+1))
        done
        if [ ! -e /dev/rbd/$DEV ]; then
          echo "Device $DEV was unresponsive"
          continue
        fi
      fi
    fi
  done < "$RBDMAPFILE"
  [[ $RET -eq 0 ]] && { echo "Success"; } || { echo "Failed"; }

  # Exit in specified
  if [[ -e $1 && $1 = "-m" ]]; then exit 0 ; fi;

  # Mount new rbd
  if [ "$newrbd" ]; then
    echo "Mounting all filesystems"
    mount -a
    [[ $? -eq 0 ]] && { echo "Success"; } || { echo "Failed"; }
  fi
}

do_unmap() {
  echo "* Stopping $DESC"
  RET=0
  # Recursive umount that depends /dev/rbd*
  MNTDEP=$(findmnt --mtab | awk '$2 ~ /^\/dev\/rbd[0-9]*$/ {print $1}' | sort -r)
  for MNT in $MNTDEP; do
    umount $MNT
  done
  # Unmap all rbd device
  cd /sys/bus/rbd/devices/
  if ls * >/dev/null 2>&1; then
    for DEV in *; do
      echo "Unmap: $DEV"
      echo $DEV > /sys/bus/rbd/remove
      [ $? -ne "0" ] && RET=1
    done
  fi
  [[ $RET -ne "1" ]] && { echo "Success"; } || { echo "Failed"; }
}


case "$1" in
  start)
  do_map $2
  ;;

  stop)
  do_unmap
  ;;

  reload)
  do_map
  ;;

  status)
  ls /sys/bus/rbd/devices/
  ;;

  *)
  echo "Usage: rbdmap {start|stop|reload|status}"
  exit 1
  ;;
esac

exit 0
